using System;
using System.Reflection;

using Xamarin.Forms;

namespace Outcoder.UI.Xaml
{
	/// <summary>
	/// Provides a means to attach a <c>VisualElement</c>
	/// to the ViewModel infrastructure via automatic data binding
	/// to various viewmodel properties.
	/// </summary>
	public interface IViewBinder
	{
		/// <summary>
		/// Attaches a <c>VisualElement</c>
		/// to the ViewModel infrastructure via automatic data binding
		/// to various viewmodel properties.
		/// </summary>
		/// <param name="visualElement">The <c>VisualElement</c> to attach.</param>
 		void BindToInfrastructure(VisualElement visualElement);
	}

	/// <summary>
	/// The default implementation of the <c>IViewBinder</c>.
	/// </summary>
	public class ViewBinder : IViewBinder
	{
		public void BindToInfrastructure(VisualElement visualElement)
		{
			var viewModel = visualElement.BindingContext;
			if (viewModel != null && visualElement.Navigation != null)
			{
				INavigation navigation = visualElement.Navigation;

				if (navigation != null)
				{
					Type viewModelType = viewModel.GetType();
					PropertyInfo propertyInfo = viewModelType.GetProperty("Navigation", typeof(INavigation));
					if (propertyInfo != null)
					{
						propertyInfo.SetValue(viewModel, navigation);
					}

					Dependency.Register<INavigation>(navigation);
				}
			}

			//visualElement.SetBinding(VisualElement.NavigationProperty, new Binding("Navigation"));
			if (visualElement is Page)
			{
				visualElement.SetBinding(Page.IsBusyProperty, new Binding("Busy"));
				visualElement.SetBinding(Page.TitleProperty, new Binding("Title"));
			}
		}
	}

	public static class ViewBinderExtensions
	{
		/// <summary> 
		/// Attaches a <c>VisualElement</c>
		/// to the infrastructure via automatic data binding
		/// to various viewmodel properties.
		/// </summary>
		/// <param name="visualElement">The current <c>VisualElement</c>.</param>
		public static void BindToInfrastructure(this VisualElement visualElement)
		{
			var viewBinder = Dependency.Resolve<IViewBinder, ViewBinder>();
			viewBinder.BindToInfrastructure(visualElement);
		}
	}
}